package service

import (
	"bytes"
	"context"
	"crypto/tls"
	"encoding/json"
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"strings"
	"time"

	"github.com/example/video_backend/internal/model"
	"github.com/example/video_backend/internal/repository"
	"github.com/example/video_backend/pkg/logger"
	"github.com/spf13/viper"
	"go.uber.org/zap"
	"gorm.io/gorm"
)

// DeepSeekService DeepSeek对话服务接口
type DeepSeekService interface {
	// 创建新对话
	CreateConversation(ctx context.Context, userID uint, title string) (*model.Conversation, error)
	// 获取用户对话列表
	GetUserConversations(ctx context.Context, userID uint, page, pageSize int) ([]*model.Conversation, int64, error)
	// 获取对话详情
	GetConversation(ctx context.Context, id uint) (*model.Conversation, error)
	// 更新对话
	UpdateConversation(ctx context.Context, conversation *model.Conversation) error
	// 删除对话
	DeleteConversation(ctx context.Context, id uint) error
	// 发送消息
	SendMessage(ctx context.Context, conversationID uint, userID uint, content string) (*model.Message, error)
	// 获取对话消息
	GetConversationMessages(ctx context.Context, conversationID uint, page, pageSize int) ([]*model.Message, error)
	// 调用DeepSeek API进行对话
	ChatWithDeepSeek(ctx context.Context, conversationID uint, userID uint, content string, functions []model.FunctionDefinition) (*model.Message, *model.FunctionCall, error)
}

// deepSeekService 实现DeepSeekService接口
type deepSeekService struct {
	conversationRepo repository.ConversationRepository
	messageRepo      repository.MessageRepository
	db               *gorm.DB
	dsAPIKey         string
	dsBaseURL        string
	dsAPIURL         string
	mcpServiceURL    string
}

// NewDeepSeekService 创建DeepSeek服务实例
func NewDeepSeekService(
	conversationRepo repository.ConversationRepository,
	messageRepo repository.MessageRepository,
) DeepSeekService {
	// 从配置中读取DeepSeek API设置
	dsAPIKey := viper.GetString("deepseek.api_key")
	dsAPIURL := viper.GetString("deepseek.api_url")
	// 从配置中读取MCP服务设置
	mcpServiceURL := viper.GetString("mcp.service_url")

	// 提取基础URL（去掉路径部分）
	dsBaseURL := dsAPIURL
	if idx := strings.LastIndex(dsAPIURL, "/"); idx > 0 {
		dsBaseURL = dsAPIURL[:idx]
	}

	// 获取数据库连接
	db := model.DB

	return &deepSeekService{
		conversationRepo: conversationRepo,
		messageRepo:      messageRepo,
		db:               db,
		dsAPIKey:         dsAPIKey,
		dsBaseURL:        dsBaseURL,
		dsAPIURL:         dsAPIURL,
		mcpServiceURL:    mcpServiceURL,
	}
}

// CreateConversation 创建新对话
func (s *deepSeekService) CreateConversation(ctx context.Context, userID uint, title string) (*model.Conversation, error) {
	conversation := &model.Conversation{
		UserID: userID,
		Title:  title,
	}

	if err := s.conversationRepo.Create(ctx, conversation); err != nil {
		logger.Error("Create conversation error", zap.Error(err))
		return nil, err
	}

	return conversation, nil
}

// GetUserConversations 获取用户对话列表
func (s *deepSeekService) GetUserConversations(ctx context.Context, userID uint, page, pageSize int) ([]*model.Conversation, int64, error) {
	return s.conversationRepo.GetUserConversations(ctx, userID, page, pageSize)
}

// GetConversation 获取对话详情
func (s *deepSeekService) GetConversation(ctx context.Context, id uint) (*model.Conversation, error) {
	return s.conversationRepo.GetByID(ctx, id)
}

// UpdateConversation 更新对话
func (s *deepSeekService) UpdateConversation(ctx context.Context, conversation *model.Conversation) error {
	return s.conversationRepo.Update(ctx, conversation)
}

// DeleteConversation 删除对话
func (s *deepSeekService) DeleteConversation(ctx context.Context, id uint) error {
	// 事务处理
	tx := s.db.WithContext(ctx).Begin()
	if tx.Error != nil {
		return tx.Error
	}
	defer func() {
		if r := recover(); r != nil {
			tx.Rollback()
		}
	}()

	// 删除对话的所有消息
	messageRepo := repository.NewMessageRepository(tx)
	if err := messageRepo.DeleteConversationMessages(ctx, id); err != nil {
		tx.Rollback()
		logger.Error("Delete conversation messages error", zap.Error(err))
		return err
	}

	// 删除对话
	conversationRepo := repository.NewConversationRepository(tx)
	if err := conversationRepo.Delete(ctx, id); err != nil {
		tx.Rollback()
		logger.Error("Delete conversation error", zap.Error(err))
		return err
	}

	return tx.Commit().Error
}

// SendMessage 发送消息
func (s *deepSeekService) SendMessage(ctx context.Context, conversationID uint, userID uint, content string) (*model.Message, error) {
	// 检查对话是否存在
	conversation, err := s.conversationRepo.GetByID(ctx, conversationID)
	if err != nil {
		logger.Error("Get conversation error", zap.Error(err))
		return nil, err
	}
	if conversation == nil {
		return nil, errors.New("对话不存在")
	}

	// 检查用户是否有权限访问该对话
	if conversation.UserID != userID {
		return nil, errors.New("无权访问该对话")
	}

	// 创建用户消息
	message := &model.Message{
		ConversationID: conversationID,
		UserID:         userID,
		Role:           model.MessageRoleUser,
		Content:        content,
	}

	if err := s.messageRepo.Create(ctx, message); err != nil {
		logger.Error("Create message error", zap.Error(err))
		return nil, err
	}

	// 更新对话的最后活跃时间
	s.conversationRepo.UpdateLastActive(ctx, conversationID)

	return message, nil
}

// GetConversationMessages 获取对话消息
func (s *deepSeekService) GetConversationMessages(ctx context.Context, conversationID uint, page, pageSize int) ([]*model.Message, error) {
	// 检查对话是否存在
	conversation, err := s.conversationRepo.GetByID(ctx, conversationID)
	if err != nil {
		logger.Error("Get conversation error", zap.Error(err))
		return nil, err
	}
	if conversation == nil {
		return nil, errors.New("对话不存在")
	}

	return s.messageRepo.GetConversationMessages(ctx, conversationID, page, pageSize)
}

// DeepSeekMessage DeepSeek API消息格式
type DeepSeekMessage struct {
	Role    string `json:"role"`
	Content string `json:"content"`
}

// DeepSeekRequest DeepSeek API请求格式
type DeepSeekRequest struct {
	Model       string         `json:"model"`
	Messages    []DeepSeekMessage `json:"messages"`
	Functions   []model.FunctionDefinition `json:"functions,omitempty"`
	Temperature float64        `json:"temperature,omitempty"`
}

// DeepSeekResponse DeepSeek API响应格式
type DeepSeekResponse struct {
	ID      string `json:"id"`
	Object  string `json:"object"`
	Created int64  `json:"created"`
	Model   string `json:"model"`
	Choices []struct {
		Index   int `json:"index"`
		Message struct {
			Role         string              `json:"role"`
			Content      string              `json:"content,omitempty"`
			FunctionCall model.FunctionCall `json:"function_call,omitempty"`
		}
	}
}

// MCPToolResponse MCP服务返回的工具定义响应结构
type MCPToolResponse struct {
	Tools []model.FunctionDefinition `json:"tools"`
}

// getToolsFromMCPService 从MCP服务获取工具定义
func (s *deepSeekService) getToolsFromMCPService(ctx context.Context, content string) ([]model.FunctionDefinition, error) {
	// 如果MCP服务URL未配置，返回空列表
	if s.mcpServiceURL == "" {
		return []model.FunctionDefinition{}, nil
	}

	// 构建请求体
	reqBody := map[string]string{
		"query": content,
	}
	reqData, err := json.Marshal(reqBody)
	if err != nil {
		logger.Error("Marshal MCP request body error", zap.Error(err))
		return nil, err
	}

	// 创建HTTP请求
	httpReq, err := http.NewRequestWithContext(ctx, "POST", s.mcpServiceURL+"/api/tools", bytes.NewReader(reqData))
	if err != nil {
		logger.Error("Create MCP HTTP request error", zap.Error(err))
		return nil, err
	}

	// 设置请求头
	httpReq.Header.Set("Content-Type", "application/json")

	// 从配置中读取MCP服务超时设置
	mcpTimeout := viper.GetInt("mcp.timeout")
	if mcpTimeout <= 0 {
		mcpTimeout = 10 // 默认10秒
	}

	// 创建HTTP客户端
	client := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
		},
		Timeout: time.Duration(mcpTimeout) * time.Second,
	}

	// 发送请求
	resp, err := client.Do(httpReq)
	if err != nil {
		logger.Error("Send MCP HTTP request error", zap.Error(err))
		// 记录错误但继续执行，不影响主流程
		return []model.FunctionDefinition{}, nil
	}
	defer resp.Body.Close()

	// 读取响应体
	respBody, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		logger.Error("Read MCP response body error", zap.Error(err))
		return []model.FunctionDefinition{}, nil
	}

	// 检查响应状态
	if resp.StatusCode != http.StatusOK {
		logger.Error("MCP service returned non-200 status", zap.Int("status_code", resp.StatusCode), zap.String("response", string(respBody)))
		return []model.FunctionDefinition{}, nil
	}

	// 解析响应
	var mcpResp MCPToolResponse
	if err := json.Unmarshal(respBody, &mcpResp); err != nil {
		logger.Error("Unmarshal MCP response body error", zap.Error(err))
		return []model.FunctionDefinition{}, nil
	}

	return mcpResp.Tools, nil
}

// ChatWithDeepSeek 调用DeepSeek API进行对话
func (s *deepSeekService) ChatWithDeepSeek(ctx context.Context, conversationID uint, userID uint, content string, functions []model.FunctionDefinition) (*model.Message, *model.FunctionCall, error) {
	// 保存用户消息
	userMessage, err := s.SendMessage(ctx, conversationID, userID, content)
	if err != nil {
		return nil, nil, err
	}

	// 获取对话历史
	historyMessages, err := s.messageRepo.GetConversationMessages(ctx, conversationID, 1, 100)
	if err != nil {
		logger.Error("Get conversation messages error", zap.Error(err))
		return nil, nil, err
	}

	// 构建请求消息
	var requestMessages []DeepSeekMessage
	for _, msg := range historyMessages {
		requestMessages = append(requestMessages, DeepSeekMessage{
			Role:    msg.Role,
			Content: msg.Content,
		})
	}

	// 从配置中读取模型和温度设置
	dsModel := viper.GetString("deepseek.model")
	temperature := viper.GetFloat64("deepseek.temperature")
	maxTokens := viper.GetInt("deepseek.max_tokens")

	// 构建DeepSeek API请求
	reqBody := DeepSeekRequest{
		Model:       dsModel,
		Messages:    requestMessages,
		Temperature: temperature,
	}

	// 从MCP服务获取工具定义，并与传入的functions合并
	mcpTools, err := s.getToolsFromMCPService(ctx, content)
	if err != nil {
		logger.Error("Get tools from MCP service error", zap.Error(err))
		// 记录错误但继续执行
	}

	// 合并从MCP服务获取的工具和传入的工具
	allTools := append([]model.FunctionDefinition{}, mcpTools...)
	if len(functions) > 0 {
		allTools = append(allTools, functions...)
	}

	// 如果有工具定义，添加到请求中
	if len(allTools) > 0 {
		reqBody.Functions = allTools
	}
	
	// 序列化请求体
	var reqData []byte
	var jsonErr error
	// 如果配置了max_tokens，添加到请求中
	if maxTokens > 0 {
		// 定义一个临时结构体用于添加max_tokens字段
		type DeepSeekRequestWithMaxTokens struct {
			DeepSeekRequest
			MaxTokens int `json:"max_tokens,omitempty"`
		}
		
		// 创建带max_tokens的请求结构体
		reqBodyWithMaxTokens := DeepSeekRequestWithMaxTokens{
			DeepSeekRequest: reqBody,
			MaxTokens:       maxTokens,
		}
		
		// 序列化请求体（带max_tokens）
		reqData, jsonErr = json.Marshal(reqBodyWithMaxTokens)
	} else {
		// 序列化请求体
		reqData, jsonErr = json.Marshal(reqBody)
	}
	
	if jsonErr != nil {
		logger.Error("Marshal request body error", zap.Error(jsonErr))
		return nil, nil, jsonErr
	}

	// 创建HTTP请求（使用完整的API URL）
	httpReq, err := http.NewRequestWithContext(ctx, "POST", s.dsAPIURL, bytes.NewReader(reqData))
	if err != nil {
		logger.Error("Create HTTP request error", zap.Error(err))
		return nil, nil, err
	}

	// 设置请求头
	httpReq.Header.Set("Content-Type", "application/json")
	httpReq.Header.Set("Authorization", "Bearer " + s.dsAPIKey)

	// 从配置中读取超时设置
	timeout := viper.GetInt("deepseek.timeout")
	if timeout <= 0 {
		timeout = 60 // 默认60秒
	}

	// 创建HTTP客户端（禁用SSL验证，仅用于测试环境）
	client := &http.Client{
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{InsecureSkipVerify: true},
		},
		Timeout: time.Duration(timeout) * time.Second,
	}

	resp, err := client.Do(httpReq)
	if err != nil {
		logger.Error("Send HTTP request error", zap.Error(err))
		return nil, nil, err
	}
	defer resp.Body.Close()

	// 读取响应体
	respBody, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		logger.Error("Read response body error", zap.Error(err))
		return nil, nil, err
	}

	// 检查响应状态
	if resp.StatusCode != http.StatusOK {
		logger.Error("DeepSeek API returned non-200 status", zap.Int("status_code", resp.StatusCode), zap.String("response", string(respBody)))
		return nil, nil, fmt.Errorf("deepseek api returned status %d: %s", resp.StatusCode, string(respBody))
	}

	// 解析响应
	var deepSeekResp DeepSeekResponse
	if err := json.Unmarshal(respBody, &deepSeekResp); err != nil {
		logger.Error("Unmarshal response body error", zap.Error(err))
		return nil, nil, err
	}

	// 处理响应
	if len(deepSeekResp.Choices) == 0 {
		return nil, nil, errors.New("no choices in response")
	}

	assistantMsg := deepSeekResp.Choices[0].Message

	// 检查是否需要调用函数
	if assistantMsg.FunctionCall.Name != "" {
		// 返回函数调用信息，不保存到消息历史
		return userMessage, &assistantMsg.FunctionCall, nil
	}

	// 保存助手回复
	assistantMessage := &model.Message{
		ConversationID: conversationID,
		UserID:         userID,
		Role:           model.MessageRoleAssistant,
		Content:        assistantMsg.Content,
	}

	if err := s.messageRepo.Create(ctx, assistantMessage); err != nil {
		logger.Error("Create assistant message error", zap.Error(err))
		// 即使保存失败，也返回消息内容
		return userMessage, nil, nil
	}

	// 更新对话的最后活跃时间
	s.conversationRepo.UpdateLastActive(ctx, conversationID)

	return userMessage, nil, nil
}